package com.food.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.food.config.FoodException;
import com.food.config.ResultCodeEnum;
import com.food.mapper.*;
import com.food.pojo.*;
import com.food.pojo.constant.CaloriesConstant;
import com.food.service.CaloriesService;
import com.food.util.SecurityUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author beixiang
 * @version 1.0
 * @description TODO
 * @date 2023/6/25 19:26
 */

@Slf4j
@Service
public class CaloriesServiceImpl extends ServiceImpl<CaloriesIngestibleUserMapper, CaloriesIngestibleUser> implements CaloriesService {

    @Autowired
    UsersMapper usersMapper;
    @Autowired
    CaloriesFoodUserMapper caloriesFoodUserMapper;
    @Autowired
    CaloriesFoodMapper caloriesFoodMapper;
    @Autowired
    CaloriesRecordsUserMapper caloriesRecordsUserMapper;
    @Autowired
    CaloriesIngestibleUserMapper caloriesIngestibleUserMapper;

    @Override
    public Boolean insertCaloriesFoodUser(CaloriesFoodUser caloriesFoodUser) {
        SecurityUtil.Users user = SecurityUtil.getUser();
        Integer userId =user.getUserId();
        if(caloriesFoodUser!=null){
            caloriesFoodUser.setUserId(userId);
        }
        int insert = caloriesFoodUserMapper.insert(caloriesFoodUser);
        if (insert > 0) {

            return true;
        } else {
            return false;
        }
    }

    @Override
    public Boolean deleteCaloriesFoodUser(Integer id) {
        int delete = caloriesFoodUserMapper.deleteById(id);
        if (delete > 0) {

            return true;
        } else {
            return false;
        }
    }

    @Override
    public Page<CaloriesFoodUser> selectCaloriesFoodUser(Integer page, Integer limit) {
        //获得用户id
        SecurityUtil.Users user = SecurityUtil.getUser();
        Integer userid =user.getUserId();
        log.info("用户id{}",userid);
        //传入分页参数
        Page<CaloriesFoodUser> pageNum = new Page<>(page, limit);
        LambdaQueryWrapper<CaloriesFoodUser> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //拼接用户id
        lambdaQueryWrapper.eq(CaloriesFoodUser::getUserId, userid);
        lambdaQueryWrapper.orderByDesc(CaloriesFoodUser::getId);
        Page<CaloriesFoodUser> caloriesFoodUserPage = caloriesFoodUserMapper.selectPage(pageNum, lambdaQueryWrapper);
        return caloriesFoodUserPage;
    }

    @Override
    public Page<CaloriesFood> selectCaloriesFood(Integer page, Integer limit) {
        //传入分页参数
        Page<CaloriesFood> pageNum = new Page<>(page, limit);
        LambdaQueryWrapper<CaloriesFood> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        Page<CaloriesFood> caloriesFoodPage = caloriesFoodMapper.selectPage(pageNum, lambdaQueryWrapper);
        return caloriesFoodPage;
    }

    @Override
    @Transactional
    public Boolean insertCaloriesRecordsUser(List<RecordsDto> recordsDtos) {

        //美食名字去重，卡路里相加。
        Map<String, Integer> hashMap = new HashMap<>();
        for(RecordsDto recordsDto:recordsDtos){
            if(hashMap.containsKey(recordsDto.getFoodName())){
                int value = hashMap.get(recordsDto.getFoodName()) + recordsDto.getTotalCalorie();
                hashMap.put(recordsDto.getFoodName(),value);
            }else {
                hashMap.put(recordsDto.getFoodName(),recordsDto.getTotalCalorie());
            }
        }
        //创建对象集合
        ArrayList<CaloriesRecordsUser> recordsUsers = new ArrayList<>();
        //获得用户id
        SecurityUtil.Users user = SecurityUtil.getUser();
        Integer userid =user.getUserId();
        //创建当前时间戳
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
        simpleDateFormat.applyPattern("yyyy-MM-dd HH:mm:ss");
        String format = simpleDateFormat.format(date);

        AtomicReference<Integer> addCalorieNew = new AtomicReference<>(0);

        //遍历map插入数据

        Set<Map.Entry<String, Integer>> entries = hashMap.entrySet();
        entries.stream().forEach(entrie -> {
            CaloriesRecordsUser recordsUser = new CaloriesRecordsUser();
            recordsUser.setUserId(userid);
            recordsUser.setFoodName(entrie.getKey());
            recordsUser.setTotalCalorie(entrie.getValue());
            recordsUser.setType("饮食摄入");
            recordsUser.setTime(format);
            // caloriesRecordsUser 插入
            caloriesRecordsUserMapper.insert(recordsUser);

            Integer value = entrie.getValue();
            addCalorieNew.updateAndGet(v -> v + value);
        });

        // `calories_ingestible_user`表 add_calorie 字段增加
        log.info("addCalorieNew = {}", addCalorieNew);
        Integer result = caloriesIngestibleUserMapper.updateByUserId(userid, addCalorieNew.get());
        if (result < 0) {
            throw new FoodException(ResultCodeEnum.UNKNOWN_ERROR);
        }

        return true;
    }

    @Override
    @Transactional
    public CaloriesIngestibleUserDto getUserRemainingCalories(Integer userId) {
        // 1.根据userId查询
        CaloriesIngestibleUserDto caloriesIngestibleUserDto = baseMapper.getUserRemainingCalories(userId);

        // 2.userId如果不在表中, 从user表查下存在此用户, 存在插入
        // 2.另外一种情况, 之前存在userId在表中, 但是时间不是当日的, 也插入
        if (caloriesIngestibleUserDto == null) {
            String userName = usersMapper.selectUserByUserId(userId);
            if (userName == null) {
                throw new FoodException("非法用户");
            } else {

                CaloriesIngestibleUserDto caloriesIngestibleUser = insertCaloriesIngestibleUser(userId);

                return caloriesIngestibleUser;
            }
        }

        // 3.计算`还可摄入卡路里` 的准备
        Integer totalCalorie = caloriesIngestibleUserDto.getTotalCalorie();
        Integer reduceCalorie = caloriesIngestibleUserDto.getReduceCalorie();
        Integer addCalorie = caloriesIngestibleUserDto.getAddCalorie();
        // 还可摄入卡路里 = 推荐摄入 + 运动消耗 - 饮食摄入
        caloriesIngestibleUserDto.setAvailableCalories(totalCalorie + reduceCalorie - addCalorie);

        return caloriesIngestibleUserDto;
    }

    @Transactional
    public CaloriesIngestibleUserDto insertCaloriesIngestibleUser(Integer userId) {
        CaloriesIngestibleUserDto caloriesIngestibleUser = new CaloriesIngestibleUserDto();
        caloriesIngestibleUser.setUserId(userId);
        caloriesIngestibleUser.setTotalCalorie(CaloriesConstant.TOTAL_CALORIE);
        caloriesIngestibleUser.setAddCalorie(CaloriesConstant.ADD_CALORIE);
        caloriesIngestibleUser.setReduceCalorie(CaloriesConstant.REDUCE_CALORIE);
        caloriesIngestibleUser.setTime(String.valueOf(LocalDateTime.now()));
        Integer integer = baseMapper.insertCaloriesIngestibleUser(caloriesIngestibleUser);
        if (integer < 0) {
            throw new FoodException(ResultCodeEnum.UNKNOWN_ERROR);
        }

        caloriesIngestibleUser.setAvailableCalories(CaloriesConstant.RECOMMENDED_CALORIES);
        return caloriesIngestibleUser;
    }

    @Override
    @Transactional
    public void addUserReduceCalorie(CaloriesRecordsUser caloriesRecordsUser) {
        Integer result1 = caloriesRecordsUserMapper.insertCaloriesRecordsUser(caloriesRecordsUser);
        if (result1 < 0) {
            throw new FoodException("插入失败");
        }
        Integer result2 = caloriesIngestibleUserMapper.updateReduceCalorie(caloriesRecordsUser);
        if (result2 < 0) {
            throw new FoodException("更新失败");
        }
    }

    @Override
    public CaloriesRecordsUserDto getUserCaloriesToday(Integer userId) {
        CaloriesRecordsUserDto caloriesRecordsUserDto = new CaloriesRecordsUserDto();

        List<CaloriesRecordsUser> dietIntake = caloriesRecordsUserMapper.getUserCaloriesToday(userId, CaloriesConstant.DIET_INTAKE);
        List<CaloriesRecordsUser> exerciseExpenditure = caloriesRecordsUserMapper.getUserCaloriesToday(userId, CaloriesConstant.EXERCISE_EXPENDITURE);

        // 饮食摄入
        caloriesRecordsUserDto.setDietIntake(dietIntake);
        // 运动消耗
        caloriesRecordsUserDto.setExerciseExpenditure(exerciseExpenditure);

        return caloriesRecordsUserDto;
    }
}

